import axios, {
  AxiosInstance,
  AxiosError,
  AxiosRequestConfig,
  AxiosResponse,
  InternalAxiosRequestConfig,
} from "axios";
import qs from "qs";

// 数据返回的接口
// 定义请求响应参数，不含data
interface Result {
  code: number;
  msg: string;
}

// 请求响应参数，包含data
interface ResultData<T = any> extends Result {
  data?: T;
}
// const URL: string = appConfig.requestUrl
const URL: string = import.meta.env.VITE_BASE_API;
console.log("VITE_BASE_API:", import.meta.env.VITE_BASE_API);

const config = {
  // 默认地址
  baseURL: URL as string,
  // 设置超时时间
  timeout: 20000,
  // 跨域时候允许携带凭证
  withCredentials: false,
};

class RequestHttp {
  // 定义成员变量并指定类型
  service: AxiosInstance;
  public constructor(config: AxiosRequestConfig) {
    // 实例化axios
    this.service = axios.create(config);

    /**
     * 请求拦截器
     * 客户端发送请求 -> [请求拦截器] -> 服务器
     * token校验(JWT) : 接受服务器返回的token,存储到vuex/pinia/本地储存当中
     */
    this.service.interceptors.request.use(
      (config: InternalAxiosRequestConfig) => {
        if (config.headers.ignoreValidate) {
          // console.log("request:", config)
        } else {
          let accessToken = "";
          // console.log("request-token:", accessToken)
          if (accessToken) {
            config.headers["accessToken"] = accessToken;
          } else {
            config.headers["isToken"] = false;
          }
        }
        return config;
      },
      (error: AxiosError) => {
        // 请求报错
        Promise.reject(error);
      }
    );

    /**
     * 响应拦截器
     * 服务器换返回信息 -> [拦截统一处理] -> 客户端JS获取到信息
     */
    this.service.interceptors.response.use(
      (response: AxiosResponse) => {
        const { data, config } = response; // 解构
        // 全局错误信息拦截（防止下载文件得时候返回数据流，没有code，直接报错）

        const code = data.code;
        const msg = data.msg || data.message;
        if (
          code === 401 ||
          code === 100000 ||
          code === 100040 ||
          code === 100050
        ) {
          // const userStore = useUserStore(pinia);
          // userStore.logout();
          return Promise.reject(data);
        } else if (data.code != 200 && data.code != 0) {
          return Promise.reject(data);
        }
        //下载返回数据
        if (config.responseType == "blob") {
          return response;
        }
        return data;
      },
      (error: AxiosError) => {
        const { response } = error;
        if (response) {
          this.handleCode(response.status);
        }
        if (!window.navigator.onLine) {
          // 可以跳转到错误页面，也可以不做操作
          // return router.replace({
          //  path: '/404'
          // });
        }
      }
    );
  }
  handleCode(code: number): void {
    switch (code) {
      case 401:
        break;
      default:
        break;
    }
  }

  // 常用方法封装
  get<T>(
    url: string,
    params?: object,
    config?: AxiosRequestConfig
  ): Promise<ResultData<T>> {
    let getConfig: AxiosRequestConfig = { params, data: {} };
    if (config != undefined) {
      getConfig = Object.assign(getConfig, config);
    }
    return this.service.get(url, getConfig);
  }

  post<T>(
    url: string,
    params?: object,
    config?: AxiosRequestConfig
  ): Promise<ResultData<T>> {
    return this.service.post(url, params, config);
  }

  form<T>(
    url: string,
    params?: object,
    config?: AxiosRequestConfig
  ): Promise<ResultData<T>> {
    let formParams = qs.stringify(params);

    if (!config) config = {};
    if (!config.headers) config.headers = {};
    config.headers = Object.assign(config.headers, {
      "Content-Type": "application/x-www-form-urlencoded",
    });
    return this.service.post(url, formParams, config);
  }

  uploadFile<T>(params?: object): Promise<ResultData<T>> {
    return this.service.post("/file-server/upload", params, {
      headers: {
        "Content-Type": "multipart/form-data",
      },
    });
  }
}

// 导出一个实例对象
export default new RequestHttp(config);
